-
-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automated retries #1776
base: master
Are you sure you want to change the base?
Automated retries #1776
Conversation
eb65eb5
to
7c875d1
Compare
7c875d1
to
c0157fc
Compare
8757074
to
09cb758
Compare
f79f837
to
ccbde0d
Compare
ccbde0d
to
15c799d
Compare
9a13279
to
7362b29
Compare
If a stacker has no send wallets, they would miss notifications about failed payments because they would never get retried. This commit fixes this by making the notifications query aware if the stacker has send wallets. This way, it can tell if a notification will be retried or not.
7362b29
to
4a4658d
Compare
As mentioned in a previous commit, I want to show anything that will not be attempted anymore in notifications. Before, I wanted to hide manually cancelled invoices but to not change experience unnecessarily and to decrease mental overhead, I changed my mind.
bc4b66c
to
f95d71b
Compare
How do you think about |
Notifications are now aware of if a stacker has send wallets via a new column With this information, I simplified the notification logic such that filter for failed payment notifications is exactly the inverse of the filter for when automated retries should be attempted. To achieve this, I also reverted my decision to not show failed payments with This means that if someone enables a send wallet, some notifications might disappear if they will now get automatically retried and vice versa. I think this is not bad UX but actually good. edit: just saw your reply
oof, you are right, a device with no send wallets would overwrite that information 🙄 Footnotes
|
I agree. Anyway, to add some brainstorming. In a situation where we're worried about invoice "waste," don't want to retry without send wallets, and I'm thinking about the refactor, I think we should just send We can probably write a graphql interface for paid action input types that requires |
0519549
to
804f58c
Compare
dea2e7a now always retries, even without send wallets, to make sure that failed payments eventually show up in notifications. However, there was an issue if a stacker goes offline longer than we would try automated retries. In that case, the payment counter will not reach the maximum and we need to check This works to show the notification in /notifications, but not for the indicator, since the indicator assumes that To fix this, I added a You can test this case with the following patch which does the following thing:
diff --git a/components/use-has-new-notes.js b/components/use-has-new-notes.js
index dcc843f3..7d489056 100644
--- a/components/use-has-new-notes.js
+++ b/components/use-has-new-notes.js
@@ -11,7 +11,7 @@ export function HasNewNotesProvider ({ me, children }) {
SSR
? {}
: {
- pollInterval: NORMAL_POLL_INTERVAL,
+ pollInterval: 1_000,
nextFetchPolicy: 'cache-and-network',
onCompleted: ({ hasNewNotes }) => {
if (!hasNewNotes) {
diff --git a/components/use-qr-payment.js b/components/use-qr-payment.js
index dddc53e9..de766618 100644
--- a/components/use-qr-payment.js
+++ b/components/use-qr-payment.js
@@ -20,7 +20,7 @@ export default function useQrPayment () {
let paid
const cancelAndReject = async (onClose) => {
if (!paid && cancelOnClose) {
- const updatedInv = await invoice.cancel(inv, { userCancel: true })
+ const updatedInv = await invoice.cancel(inv, { userCancel: false })
reject(new InvoiceCanceledError(updatedInv))
}
resolve(inv)
diff --git a/lib/constants.js b/lib/constants.js
index 9ec20245..e35dc2f5 100644
--- a/lib/constants.js
+++ b/lib/constants.js
@@ -201,8 +201,8 @@ export const WALLET_CREATE_INVOICE_TIMEOUT_MS = 45_000
// interval between which failed invoices are returned to a client for automated retries.
// retry-after must be high enough such that intermediate failed invoices that will already
// be retried by the client due to sender or receiver fallbacks are not returned to the client.
-export const WALLET_RETRY_AFTER_MS = 60_000 // 1 minute
-export const WALLET_RETRY_BEFORE_MS = 86_400_000 // 24 hours
+export const WALLET_RETRY_AFTER_MS = 5_000 // 1 minute
+export const WALLET_RETRY_BEFORE_MS = 10_000 // 24 hours
// we want to attempt a payment three times so we retry two times
export const WALLET_MAX_RETRIES = 2
// when a pending retry for an invoice should be considered expired and can be attempted again
diff --git a/wallets/index.js b/wallets/index.js
index d72227b5..94b8043d 100644
--- a/wallets/index.js
+++ b/wallets/index.js
@@ -254,6 +254,7 @@ function RetryHandler ({ children }) {
useEffect(() => {
// we always retry failed invoices, even if the user has no wallets on any client
// to make sure that failed payments will always show up in notifications eventually
+ return
const retryPoll = async () => {
let failedInvoices |
804f58c
to
ddc115e
Compare
I'm surprised the indicator query couldn't be changed instead. |
Since possibly receiving a notification about a failed payment after 1 day is bad UX, I changed it to stop automated retries after one hour.
I think this is the first case where we want to show something in notifications after a timeout. This means it already existed in the database and wasn't updated between last poll and when we want to show it. I considered to calculate And we can't create an index with an expression that depends on the current time afaik 🤔 So not sure how to change it. Using a job to update the timestamp makes everything work as expected. However, we could add a new final |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I understand why you added the job. I think it can be fixed by making the notification and indicator queries more complicated - which sucks. We'd basically need a separate queries for userCancel
or not and have to fuss with lastChecked
and sortTime
using WALLET_RETRY_BEFORE_MS
if userCancel = false
. Probably not much better than your job but it'll at least be in two places (indicator/notifications) rather than four (paidAction,indicator,notifications,worker)? I think without a refactor this is kind of where we are going to end up with this stuff.
I don't know if it's worth making those changes. Up to you. Just let me know about the ITEM_CREATE
thing and I'll give it a final QA.
@@ -567,6 +562,31 @@ export default { | |||
return true | |||
} | |||
|
|||
const invoiceActionFailed2 = await models.invoice.findFirst({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I struggled with writing a good comment since I already struggled with grasping this query, lol.
I think this didn't break anything but I didn't fully QA everything again.
Will do so after some sleep.
Oh, I am still missing the fix for
btw, I think your suggestion is much better than my job |
Description
close #1492 based on #1785, #1787
All failed invoices are returned to every client periodically via a new query
failedInvoices
. To make sure an invoice is only retried by one client at a time, we implemented expiring locks: we first try to update a new timestamp columnretryPendingSince
on the invoice. Only one client at a time will be able to successfully update the invoice. This lock expires after a minute after which another retry for the same invoice can be attempted by a client.To stop after three payment attempts (= two retries), a new integer column
Invoice.paymentAttempt
tracks at which payment attempt we are. This number is increased when we retry an invoice and passnewAttempt: true
which we do when we retry these fetched failed invoices. When the number is increased, the payment will start from the beginning with all sender and receiver wallets available.TODO:
added
userCancel
column, see #1785client only polls when it has send wallets
added
"cancelledAt" < now() - interval '${WALLET_RETRY_AFTER_MS} milliseconds'
filteradded
WALLET_RETRY_BEFORE_MS
used in this filter:new TODO since feedback:
hasNewNotes
Additional Context
see https://github.com/stackernews/stacker.news/pull/1776/files#r1907791409Checklist
Are your changes backwards compatible? Please answer below:
yes
On a scale of 1-10 how well and how have you QA'd this change and any features it might affect? Please answer below:
7
. Tested automated retries for posting, replies and zapping with this patch:Simulate multiple clients with this patch:
Test p2p zaps with this patch that makes forwards fail and disables the fallback to CCs:
For frontend changes: Tested on mobile, light and dark mode? Please answer below:
n/a
Did you introduce any new environment variables? If so, call them out explicitly here:
no